package com.lottery.material.service.admin.portaluser.impl;

import com.lottery.material.config.upload.UploadFileConfig;
import com.lottery.material.dao.conf.AreaDictMapper;
import com.lottery.material.dao.conf.BankDictMapper;
import com.lottery.material.dao.portaluser.PortalUserInfoMapper;
import com.lottery.material.dao.transaction.UserBuyRecordMapper;
import com.lottery.material.enumeration.portaluser.PortalUserInfoEnum;
import com.lottery.material.enumeration.transaction.UserBuyRecordEnum;
import com.lottery.material.pojo.conf.AreaDict;
import com.lottery.material.pojo.page.Page;
import com.lottery.material.pojo.page.PageData;
import com.lottery.material.pojo.portaluser.PortalUserInfo;
import com.lottery.material.pojo.transaction.UserBuyRecord;
import com.lottery.material.pojocustom.portaluser.PortalUserInfoCustom;
import com.lottery.material.service.admin.portaluser.PortalUserInfoService;
import com.lottery.material.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Description：前端用户信息服务接口实现类
 * Created by 朱正磊 on 2019-04-13 17:41
 */
@Slf4j
@Service("adminPortalUserInfoService")
public class PortalUserInfoServiceImpl implements PortalUserInfoService {

    private final PortalUserInfoMapper portalUserInfoMapper;

    private final UploadFileConfig uploadFileConfig;

    private final UserBuyRecordMapper userBuyRecordMapper;

    private final BankDictMapper bankDictMapper;

    private final AreaDictMapper areaDictMapper;

    @Autowired
    public PortalUserInfoServiceImpl(PortalUserInfoMapper portalUserInfoMapper,
                                     UploadFileConfig uploadFileConfig,
                                     UserBuyRecordMapper userBuyRecordMapper,
                                     BankDictMapper bankDictMapper,
                                     AreaDictMapper areaDictMapper) {
        this.portalUserInfoMapper = portalUserInfoMapper;
        this.uploadFileConfig = uploadFileConfig;
        this.userBuyRecordMapper = userBuyRecordMapper;
        this.bankDictMapper = bankDictMapper;
        this.areaDictMapper = areaDictMapper;
    }

    /**
     * description：新增一条数据
     * user 朱正磊
     * time 2019-04-20 15:14
     * @param request 请求对象
     * @param portalUserInfo 对象
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer add(HttpServletRequest request, PortalUserInfo portalUserInfo) {
        portalUserInfo.setAccessToken(UUID.randomUUID().toString());
        portalUserInfo.setCreateTime(new Date()); //创建时间
        portalUserInfo.setLogonMode((Integer) PortalUserInfoEnum.LOGON_MODE_ADMIN.getValue()); //后台注册
        if (AssertUtil.isNotEmpty(request)) { //其实可以不用加判断
            this.setPictureByOSS(request, portalUserInfo);//上传头像
        }
        if (AssertUtil.isEmpty(portalUserInfo.getUserLevel())) { //如果为空，默认设置为1
            portalUserInfo.setUserLevel(1);
        }
        portalUserInfo.setLoginPassword(MD5Util.MD5("111111")); //登录密码默认111111
        return portalUserInfoMapper.insertSelective(portalUserInfo);
    }

    /**
     * description：根据主键物理删除
     * user 朱正磊
     * time 2019-04-20 15:13
     * @param id 主键
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer deleteById(Integer id) {
        return portalUserInfoMapper.deleteByPrimaryKey(id);
    }

    /**
     * description：根据主键查询唯一数据
     * user 朱正磊
     * time 2019-04-20 15:15
     * @param id 主键
     * @return 返回唯一数据
     */
    @Override
    public PortalUserInfo findById(Integer id) {
        return portalUserInfoMapper.selectByPrimaryKey(id);
    }

    /**
     * description：根据主键修改一条数据
     * user 朱正磊
     * time 2019-04-20 15:16
     * @param request 请求对象
     * @param portalUserInfo 对象
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer updateById(HttpServletRequest request, PortalUserInfo portalUserInfo) {
        if (AssertUtil.isNotEmpty(request)) { //判断必须加
            this.setPictureByOSS(request, portalUserInfo);//上传头像
        }
        if (AssertUtil.isEmpty(portalUserInfo.getUserLevel())) { //如果为空，默认设置为1
            portalUserInfo.setUserLevel(1);
        }
        return portalUserInfoMapper.updateByPrimaryKeySelective(portalUserInfo);
    }

    /**
     * description： 设置图片（使用OSS）
     * user 朱正磊
     * time 2019-04-23 09:43
     * @param request 请求对象
     * @param portalUserInfo 前端用户对象
     */
    private void setPictureByOSS(HttpServletRequest request, PortalUserInfo portalUserInfo) {
        //采用OSS作为图片服务器
        String pictureAddressOne = OSSClientUtil.uploadFiles(uploadFileConfig,
                FileUploadUtil.getMultipartFiles(request, "pictureAddressOne"), uploadFileConfig.getPortalUserInfoModuleName());
        if (AssertUtil.isNotEmpty(pictureAddressOne)) {
            //设置用户头像
            portalUserInfo.setUserIcon(pictureAddressOne);
        }
    }

    /**
     * description： 设置图片（使用nginx）
     * user 朱正磊
     * time 2019-04-23 09:43
     * @param request 请求对象
     * @param portalUserInfo 前端用户对象
     */
    @SuppressWarnings("unused")
    private void setPictureByNginx(HttpServletRequest request, PortalUserInfo portalUserInfo) {
        //采用nginx作为图片服务器
        String pictureAddressOne = FileUploadUtil.getPictureUrl(request, uploadFileConfig.getProjectName(),
                uploadFileConfig.getPortalUserInfoModuleName(), "pictureAddressOne", FtpUtil.getFtpConfig(uploadFileConfig));
        if (AssertUtil.isNotEmpty(pictureAddressOne)) {
            //设置用户头像
            portalUserInfo.setUserIcon(pictureAddressOne);
        }
    }

    /**
     * description：根据注册方式以及用户状态查询前端用户列表信息
     * user 朱正磊
     * time 2019-04-22 14:15
     * @param logonMode 注册方式（1：前台正常流程注册；2：后台运营人员注册）
     * @param userStatus 用户状态（1：正常；2：永久封禁；3：已删除）
     * @return 返回前端用户列表信息
     */
    @Override
    public List<PortalUserInfoCustom> findPortalUserInfoByLogonMode(Integer logonMode, Integer userStatus) {
        return portalUserInfoMapper.findPortalUserInfoByLogonMode(logonMode, userStatus);
    }

    /**
     * description：查询扩展类分页列表
     * user 朱正磊
     * time 2019-04-17 17:01
     * @param page 分页对象
     * @return 返回扩展类分页列表数据
     */
    @Override
    public List<PortalUserInfoCustom> findCustomListPage(Page page) {
        List<PortalUserInfoCustom> list = portalUserInfoMapper.findCustomListPage(page);
        list.forEach(this::setCustom);
        return list;
    }

    /**
     * description：查询扩展类列表（用于导出Excel）
     * user 朱正磊
     * time 2019-04-26 17:25
     * @param pd 参数封装对象，其实本质上是一个Map
     * @return 返回扩展类列表数据
     */
    @Override
    public List<PortalUserInfoCustom> selectListAll(PageData pd) {
        List<PortalUserInfoCustom> list = portalUserInfoMapper.selectListAll(pd);
        this.formatCustomForExcel(list);//格式化需要导出Excel的列表数据
        return list;
    }

    /**
     * description：根据id集合进行查询多条扩展类数据（用于导出Excel）
     * user 朱正磊
     * time 2019-04-26 17:25
     * @param ids 选中的行数据的id拼接而成的字符串
     * @return 返回扩展类列表数据
     */
    @Override
    public List<PortalUserInfoCustom> selectListByIds(String ids) {
        List<String> asList = Arrays.asList(ids.split(","));
        List<Integer> idList = new ArrayList<>();
        asList.forEach(e -> idList.add(Integer.valueOf(e)));
        List<PortalUserInfoCustom> list = portalUserInfoMapper.selectListByIds(idList);
        this.formatCustomForExcel(list);//格式化需要导出Excel的列表数据
        return list;
    }

    /**
     * description：格式化需要导出Excel的列表数据
     * user 朱正磊
     * time 2019-04-26 17:30
     * @param list 业务列表数据
     */
    private void formatCustomForExcel(List<PortalUserInfoCustom> list) {
        Integer index = 1;
        for (PortalUserInfoCustom custom : list) {
            this.setCustom(custom);//给扩展对象设置扩展字段的值
            custom.setIndex(index);
            index ++;
        }
    }

    /**
     * description：根据主键查询唯一扩展类数据
     * user 朱正磊
     * time 2019-04-17 17:03
     * @param id 主键
     * @return 返回唯一扩展类数据
     */
    @Override
    public PortalUserInfoCustom findCustomById(Integer id) {
        PortalUserInfoCustom custom = portalUserInfoMapper.findCustomById(id);
        this.setCustom(custom);
        return custom;
    }

    /**
     * description：设置扩展类的扩展属性
     * user 朱正磊
     * time 2019-04-17 17:48
     * @param custom 扩展类对象
     */
    private void setCustom(PortalUserInfoCustom custom) {
        //创建时间
        custom.setCreateTimeFormat(CalendarUtil.dateToString(custom.getCreateTime()));
        //最近一次登录时间
        custom.setLastLoginTimeFormat(CalendarUtil.dateToString(custom.getLastLoginTime()));
        //用户类型（1：普通；2：认证；3：达人）
        custom.setUserTypeDesc(EnumUtil.getDescriptionByCodeValue(PortalUserInfoEnum.USER_TYPE,
                custom.getUserType(), PortalUserInfoEnum.class));
        //昵称是否被修改过（1：未修改；2：修改过）
        custom.setIsUpdateNickNameDesc(EnumUtil.getDescriptionByCodeValue(PortalUserInfoEnum.IS_UPDATE_NICK_NAME,
                custom.getIsUpdateNickName(), PortalUserInfoEnum.class));
        //注册方式（1：前台；2：后台）
        custom.setLogonModeDesc(EnumUtil.getDescriptionByCodeValue(PortalUserInfoEnum.LOGON_MODE,
                custom.getLogonMode(), PortalUserInfoEnum.class));
        //用户状态（1：启用；2：禁用；3：已删除）
        custom.setUserStatusDesc(EnumUtil.getDescriptionByCodeValue(PortalUserInfoEnum.USER_STATUS,
                custom.getUserStatus(), PortalUserInfoEnum.class));
        //用户余额
        String money = MathUtil.addHalfUp(custom.getGoldBuy().toString(), custom.getGoldProfit().toString(), 0);
        custom.setMoney(money);
        //银行名称
        if (AssertUtil.isNotEmpty(custom.getBankCode())) {
            custom.setBankName(bankDictMapper.findByBankCode(custom.getBankCode()).getBankName());
        }
        //省
        if (AssertUtil.isNotEmpty(custom.getProvince())) {
            AreaDict provinceArea = areaDictMapper.findByRegionId(Integer.valueOf(custom.getProvince()));
            String provinceName = provinceArea.getRegionName();
            custom.setProvinceName(provinceName);
        }
        //市
        if (AssertUtil.isNotEmpty(custom.getCity())) {
            AreaDict cityArea = areaDictMapper.findByRegionId(Integer.valueOf(custom.getCity()));
            String cityName = cityArea.getRegionName();
            custom.setCityName(cityName);
        }
        //区
        if (AssertUtil.isNotEmpty(custom.getDistrict())) {
            AreaDict districtArea = areaDictMapper.findByRegionId(Integer.valueOf(custom.getDistrict()));
            String districtName = districtArea.getRegionName();
            custom.setDistrictName(districtName);
        }
    }

    /**
     * description：批量禁用
     * user 朱正磊
     * time 2019-04-24 16:37
     * @param ids 主键集合(多个id以,进行拼接)
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer updateBatchBan(String ids) {
        Map<String, Object> data = new HashMap<>();
        data.put("idList", ListUtil.getIdList(ids));
        data.put("userStatus", PortalUserInfoEnum.USER_STATUS_FORBIDDEN.getValue());
        return portalUserInfoMapper.updateBatchBanOrNot(data);
    }

    /**
     * description：批量启用
     * user 朱正磊
     * time 2019-04-24 16:37
     * @param ids 主键集合(多个id以,进行拼接)
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer updateBatchNotBan(String ids) {
        Map<String, Object> data = new HashMap<>();
        data.put("idList", ListUtil.getIdList(ids));
        data.put("userStatus", PortalUserInfoEnum.USER_STATUS_NORMAL.getValue());
        return portalUserInfoMapper.updateBatchBanOrNot(data);
    }

    /**
     * description：根据用户昵称查询数据集合
     * user 朱正磊
     * time 2019-04-28 16:42
     * @param nickName 用户昵称
     * @param id 主键
     * @return 返回数据集合
     */
    @Override
    public List<PortalUserInfo> findByNickName(String nickName, Integer id) {
        return portalUserInfoMapper.findByNickName(nickName, id);
    }

    /**
     * description：根据登录手机号查询数据集合
     * user 朱正磊
     * time 2019-04-28 16:42
     * @param loginPhoneNumber 登录手机号
     * @param id 主键
     * @return 返回数据集合
     */
    @Override
    public List<PortalUserInfo> findByLoginPhoneNumber(String loginPhoneNumber, Integer id) {
        return portalUserInfoMapper.findByLoginPhoneNumber(loginPhoneNumber, id);
    }

    /**
     * description：调整金币
     * user 朱正磊
     * time 2019-04-29 14:44
     * @param request 请求对象
     * @return 返回持久化操作数据库状态值
     */
    @Override
    public Integer updateAddOrSub(HttpServletRequest request) {
        Integer id = Integer.valueOf(request.getParameter("id"));
        PortalUserInfo portalUserInfo = this.findById(id);
        //金币--充值
        Integer goldBuy = portalUserInfo.getGoldBuy();
        //调整方式
        Integer addOrSub = Integer.valueOf(request.getParameter("addOrSub"));
        //调整额度
        String quota = request.getParameter("quota");
        if (Objects.equals(UserBuyRecordEnum.BUY_TYPE_ADD.getValue(), addOrSub)) { //添加
            goldBuy = Integer.valueOf(MathUtil.addHalfUp(goldBuy.toString(), quota, 0));
        } else { //减少
            goldBuy = Integer.valueOf(MathUtil.subHalfUp(goldBuy.toString(), quota, 0));
        }
        portalUserInfo.setGoldBuy(goldBuy);
        Integer flag = portalUserInfoMapper.updateByPrimaryKeySelective(portalUserInfo);
        if (!Objects.equals(0, flag)) { //更新成功
            UserBuyRecord userBuyRecord = new UserBuyRecord();
            userBuyRecord.setOrderCode(IDUtil.createCode());
            userBuyRecord.setCreateTime(new Date());
            userBuyRecord.setUserId(portalUserInfo.getUserId());
            userBuyRecord.setBuyAmount(Integer.valueOf(quota));
            userBuyRecord.setPayType((Integer) UserBuyRecordEnum.PAY_TYPE_ADMIN_RECHARGE.getValue());
            userBuyRecord.setBuyType(addOrSub);
            userBuyRecord.setBuyExplain(request.getParameter("buyExplain"));
            flag = userBuyRecordMapper.insertSelective(userBuyRecord);
        }
        return flag;
    }

    /**
     * description：前端用户列表查询（用于导出Excel）（这是另外一种导出Excel的方式）
     * user 朱正磊
     * time 2019-06-05 15:00
     * @param key 缓存key
     * @param pd 参数封装对象，其实本质上是一个Map
     * @param start 开始索引（包括）
     * @param end 结束索引（不包括）
     * @param type 方法作用类型：0-查询总数据；1-分段从缓存获取数据；2-删除缓存
     * @return 返回响应对象
     */
    @Override
    public ResponseResult portalUserInfoExportMethods(String key, PageData pd, Integer start, Integer end, Integer type) {
        switch (type) {
            case 0:
                return listExtend(pd, key);
            case 1:
                return getPortalUserInfoListFromCache(key, start, end);
            case 2:
                return deletePortalUserInfoListFromCache(key);
            default:
                return ResponseResult.buildResult(400, "未知方法类型");
        }
    }

    /**
     * description：根据条件查询前端用户总数据，放入本地缓存
     * user 朱正磊
     * time 2019-06-05 15:16
     * @param pd 参数封装对象，其实本质上是一个Map
     * @param key 缓存key
     * @return 返回响应对象
     */
    private ResponseResult listExtend(PageData pd, String key) {
        List<PortalUserInfoCustom> list = selectListAll(pd);
        if (CollectionUtils.isEmpty(list)) {
            return ResponseResult.buildResult(400, "获取前端用户信息失败");
        }
        PortalUserInfoExportCacheUtil.portalUserInfoExportCacheMap.put(key, list);
        return ResponseResult.buildResult(200, "获取前端用户信息成功", list.size());
    }

    /**
     * description：分段获取本地缓存数据
     * user 朱正磊
     * time 2019-06-05 15:36
     * @param key 缓存key
     * @param start 开始索引（包括）
     * @param end 结束索引（不包括）
     * @return 返回响应对象
     */
    private ResponseResult getPortalUserInfoListFromCache(String key, Integer start, Integer end) {
        List<PortalUserInfoCustom> generalPortalUserInfoList =
                PortalUserInfoExportCacheUtil.getGeneralPortalUserInfoList(key, start, end);
        if (CollectionUtils.isEmpty(generalPortalUserInfoList)) {
            return ResponseResult.buildResult(400, "获取失败");
        }
        return ResponseResult.buildResult(200, "获取成功", generalPortalUserInfoList);
    }

    /**
     * description：删除本地缓存数据
     * user 朱正磊
     * time 2019-06-05 15:37
     * @param key 缓存key
     * @return 返回响应对象
     */
    private ResponseResult deletePortalUserInfoListFromCache(String key) {
        PortalUserInfoExportCacheUtil.deleteListByKey(key);
        return ResponseResult.buildResult(200, "删除成功");
    }

}
